﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using Microsoft.Scripting.Hosting;
using Flame.Reflection;

namespace Flame.Dlr
{
    /// <summary>
    /// Abstract class specialized for ironpython and ironruby since that uses both   
    /// Microsoft.Scripting.Hosting.ScriptScope
    /// </summary>
    public abstract class AExecutablePR : IExecutable, IStreamedOutput
    {
        internal AExecutablePR()
        {
            _engine = ScriptEngine;

            ClearScope(null);
        }

        protected ScriptEngine _engine;
        public ScriptScope Scope { get; private set; }
        protected abstract ScriptEngine ScriptEngine { get; }

        public abstract IIntellisense Intellisense { get; }
        protected abstract Result checkForSpecialType(Result cr);

        Result check(Result cr)
        {
            cr = checkForSpecialType(cr);
            try
            {
                if (cr.Data == null)
                    return Result.Null;
            }
            catch
            {
                return Result.Bad;
            }
            return cr;
        }

        public Result Execute(string script)
        {
            Result cr = new Result();
            cr.Data = _engine.Execute(script, Scope);
            return check(cr);
        }

        public void AddVariable(Variable variable)
        {
            Scope.SetVariable(variable.Name, variable.Data);
        }

        protected abstract void clearScope(ScopeParameters scopeParameters);

        public void ClearScope(ScopeParameters scopeParameters)
        {
            Scope = _engine.CreateScope();
            clearScope(scopeParameters);
            if(scopeParameters != null) scopeParameters.Apply(this);
        }

        public void Set(System.IO.Stream stream)
        {
            _engine.Runtime.IO.SetOutput(stream, Encoding.UTF8);
            _engine.Runtime.IO.SetErrorOutput(stream, Encoding.UTF8);
        }


        public abstract ResultAssembly AddAssembly(AssemblyWrapper res);
    }

}
